// 2025.03.02 16:40 星期日 阴 无事

import { toStringTypeCheck } from '../../../../Func/uniFunc/Func/toStringTypeCheck';
import { normalizeContainer } from '../../../Func';
import { listenEvent_info } from './cla_listenEvent_info';

const listenEvent_info_manaTag = 'listenEvent_info_mana';

class listenEvent_info_mana {
  get [Symbol.toStringTag]() {
    return listenEvent_info_manaTag;
  }

  constructor() {}

  /**
   * @type {listenEvent_info[]}
   */
  stack = [];

  /**
   * 添加 事件 信息
   * @param {string | HTMLElement | undefined} targetEl 给定 元素
   * @param {import('../../Func/add_remove_eventListen').eventA | undefined } event
   * @param {function | undefined} fn
   */
  addInfo(targetEl, event, fn) {
    this.stack.unshift(new listenEvent_info(targetEl, event, fn));
  }

  /**
   * 移除 事件 信息
   * @param {string | HTMLElement | undefined} targetEl 给定 元素
   * @param {import('../../Func/add_remove_eventListen').eventA | undefined } event
   * @param {function | undefined} fn
   * @returns {listenEvent_info[]}
   */
  removeInfo(targetEl, event, fn) {
    let deleteArr = this.seekForStack(targetEl, event, fn);
    for (const uniInfo of deleteArr) {
      let ind = this.stack.indexOf(uniInfo);
      this.stack.splice(ind, 1);
    }
    return deleteArr;
  }

  /**
   * 根据 元素 事件 函数 (三个可以自由组合)
   * 选取 对应的 信息集
   * @param {string | HTMLElement | undefined} targetEl 给定 元素
   * @param {import('../../Func/add_remove_eventListen').eventA | undefined } event
   * @param {function | undefined} fn
   * @returns
   */
  seekForStack(targetEl, event, fn) {
    let ret = this.stack;

    if (![null, undefined].includes(targetEl)) {
      targetEl = normalizeContainer(targetEl);

      ret = seekForProp(ret, 'targetEl', targetEl);
    }

    if (event) {
      ret = seekForProp(ret, 'event', event);
    }

    if (fn) {
      ret = seekForProp(ret, 'fn', fn);
    }

    return ret;
  }
}

/**
 * 根据 stack 数据 查询 相关 数组
 * @param {listenEvent_info[]} stack
 * @param {'targetEl' | 'event' | 'fn' } prop
 * @param {string | HTMLElement | Function} val
 */
function seekForProp(stack, prop, val) {
  let ret = [];

  for (const uniInfo of stack) {
    if (uniInfo[prop] == val) {
      ret.push(uniInfo);
    }
  }

  return ret;
}

/**
 *
 * 根据 stack 数据 查询 相关 数组
 * @param {listenEvent_info[]} listen_info
 * @param {'targetEl' | 'event' | 'fn' } prop
 * @param {string | HTMLElement | Function} val
 * @returns  {listenEvent_info[]}
 */
function forof_seekForProp(listen_info, prop, val) {
  let ret = seekForProp(listen_info, prop, val);
  return ret;
}

/**
 * 根据 可能 数组情况 获取 对应 数据
 * @param {listenEvent_info[]} listen_info
 * @param {{targetElArr:HTMLElement | HTMLElement[], eventArr:eventA | eventA[], fnArr:function | function[]}} param1
 * @returns
 */
function locate_uniArr_info(listen_info, { targetElArr, eventArr, fnArr }) {
  let ret = [];
  if (targetElArr != undefined) {
    if (targetElArr instanceof HTMLElement || targetElArr == window) {
      targetElArr = [targetElArr];
    }

    for (const target of targetElArr) {
      ret.push(...forof_seekForProp(listen_info, 'targetEl', target));
    }
    listen_info = ret;
  }

  if (eventArr != undefined) {
    ret = [];
    // 未测试
    if (toStringTypeCheck(eventArr, 'string')) {
      eventArr = [eventArr];
    }

    for (const event of eventArr) {
      ret.push(...forof_seekForProp(listen_info, 'event', event));
    }

    listen_info = ret;
  }

  if (fnArr != undefined) {
    ret = [];
    // 未测试
    if (toStringTypeCheck(fnArr, 'function')) {
      fnArr = [fnArr];
    }
    for (const fn of fnArr) {
      ret.push(...forof_seekForProp(listen_info, 'fn', fn));
    }
  }

  return ret;
}

export {
  listenEvent_info_mana,
  seekForProp,
  forof_seekForProp,
  locate_uniArr_info,
};
